package org.zxp.javacheck.parampassing;

import lombok.Data;
import org.junit.Test;

import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

/**
 * @program: effectiveJava
 * @description: 测试值传递 引用传递 字符串传递 null传递
 * @author: X-Pacific zhang
 * @create: 2019-05-21 11:06
 **/
public class ParameterPassing {
    /**
     * 值传递测试：基本数据类型传值，对形参的修改不会影响实参
     */
    @Test
    public void testValuePass() {
        ParameterPassing parameterPassing = new ParameterPassing();
        int num = 0;
        parameterPassing.testValuePassFunc(num);
        System.out.println("2:" + num);
    }

    public void testValuePassFunc(int num) {
        num = 10;
        System.out.println("1:" + num);
    }

    /**
     * String, Integer, Double等可以理解为值传递，最后的操作不会修改实参对象
     */
    @Test
    public void testStringPass() {
        ParameterPassing parameterPassing = new ParameterPassing();
        String str = "abc";
        parameterPassing.testStringPassFunc(str);
        System.out.println("2:" + str);
    }

    public void testStringPassFunc(String str) {
        str = "abcdefg";
        System.out.println("1:" + str);
    }

    /**
     * 引用类型传引用，形参和实参指向同一个内存地址（同一个对象），所以对参数的修改会影响到实际的对象
     */
    @Test
    public void testObjPass() {
        ParameterPassing parameterPassing = new ParameterPassing();
        ObjectPassing obj = new ObjectPassing();
        obj.setName("name");
        System.out.println("1:" + obj);
        parameterPassing.testObjPassFunc(obj);//执行后，name都变成了zxp
        System.out.println("3:" + obj);
    }

    public void testObjPassFunc(ObjectPassing obj) {
        obj.setName("zxp");
        System.out.println("2:" + obj);
    }

    /**
     * 1、传递的入参是null，方法内new了，也不会影响到外面null的对象，还是null的
     * 2、传递的入参不是null，方法内=null了，也不会影响到外面不是null的对象
     * 3、传递的入参不null，传递到线程中，线程运行中，外面把入参设置为null，线程内继续不是null
     * 总结，别管里面外面 null变!null !null变null 都不会隔层影响原来啥样还啥样
     */
    @Test
    public void testNullPass() throws InterruptedException {
        ParameterPassing parameterPassing = new ParameterPassing();
        ObjectPassing obj = null;
        System.out.println("1:" + obj);//null  传入null是值传递，方法内new了也白new，外面还是null
        parameterPassing.testNullPassFunc(obj);//zxp
        System.out.println("3:" + obj);//null

        System.out.println("=======================");
        obj = new ObjectPassing();
        obj.setName("name");
        System.out.println("1:" + obj);//name
        parameterPassing.testNullPassFunc2(obj);//null
        System.out.println("3:" + obj);//name

        System.out.println("=======================");
        obj = new ObjectPassing();
        obj.setName("name");
        MyThread myThread = new MyThread(obj);
        new Thread(myThread).start();
        Thread.sleep(1000);
        obj = null;
        System.out.println("2:" + obj);

        Thread.sleep(1000000);
    }

    /**
     * 1、传递的入参不是null，方法内new了，也不会影响到外面的对象
     * @throws InterruptedException
     */
    @Test
    public void testNew() throws InterruptedException {
        ObjectPassing obj = null;
        obj = new ObjectPassing();
        obj.setName("name");
        testNullPassFunc(obj);
        Thread.sleep(1000);
        System.out.println("2:" + obj);
    }

    /**
     * 1、不new也不null传递引用可以影响
     * @throws InterruptedException
     */
    @Test
    public void testNotNewNotNull() throws InterruptedException {
        ObjectPassing obj = null;
        obj = new ObjectPassing();
        obj.setName("name");
        testNullPassFunc(obj);
        Thread.sleep(1000);
        System.out.println("2:" + obj);
    }

    public void testNullPassFunc(ObjectPassing obj) {
        obj.setName("zxp");
        System.out.println("2:" + obj);
    }

    public void testNullPassFunc2(ObjectPassing obj) {
        obj = null;
        System.out.println("2:" + obj);
    }


    @Data
    static class ObjectPassing {
        private String name;
    }


    String[] arr1 = {"a","b","c","d"};

    @Test
    public void testArray() throws InterruptedException {
        //new新的数组不会影响arr2
//        ParameterPassing pp = new ParameterPassing();
//        String[] arr2 = pp.arr1 ;
//        pp.arr1 = new String[3];
//        pp.arr1[0] = "r";pp.arr1[1] = "t";pp.arr1[2] = "x";
//        for (int i = 0; i < arr2.length; i++) {
//            System.out.println("main:"+arr2[i]);
//        }

        ParameterPassing pp = new ParameterPassing();
        String[] arr2 = {"1","2","3"};
        String[] arr3 = new String[4];
        arr3[0] = "4";arr3[1] = "5";arr3[2] = "6";arr3[3] = "7";
        arr2 = arr3;
        for (int i = 0; i < arr2.length; i++) {
            System.out.println("main:"+arr2[i]);
        }
    }


    /**
     * 数组 改单独元素可以改(哪怕是null也可以改)，但是直接覆盖（包括改成null）的不可以改（内外都改不了）
     */
    @Test
    public void testByteArray(){
//        ParameterPassing pp = new ParameterPassing();
//        byte[] bb = "zq".getBytes();
//        int[] is = {1,2,3,4};
//        upArray2(bb,is);
//        System.out.println(new String(bb));
//        for (int i = 0; i < is.length; i++) {
//            System.out.println(is[i]);
//        }



        Object[] objs = {new Object(),new ParameterPassing()};
        new Thread(()->{
            try {
                new ParameterPassing().upArray3(objs);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
//        objs[0] = null;
//        objs[1] = null;
        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("outter[0]" + objs[0]);
        System.out.println("outter[1]" + objs[1]);
    }

    private void upArray(byte[] bs,int[] is){
        bs[bs.length-1] = 'a';
        is[3] = 5;
    }

    private void upArray2(byte[] bs,int[] is){
        bs = "zxp".getBytes();
        is = new int[4];
        is[0] = 1;is[1] = 1;is[2] = 1;is[3] = 1;
    }

    private void upArray3(Object[] objs) throws InterruptedException {
//        Thread.sleep(1000L);
//        System.out.println("inner[0]"+objs[0]);
//        System.out.println("inner[1]"+objs[1]);
//        objs[0] = null;
//        objs[1] = null;
        objs = null;
    }

    /**
     * 不涉及传递直接改还是可以改成功
     * 这不是值传递引用传递的范畴
     * @param args
     */
    public static void main(String[] args){
        int[] ins = {1,2,3,4};
        int old = ins[2];
        ins[2] = 5;
        System.out.println(ins[2]);
        System.out.println(old);


        Temp t1 = new Temp("1");
        Temp ot1 = t1;
        t1 = new Temp("2");
        System.out.println(ot1.getFlag());
        System.out.println(t1.getFlag());

    }

    static class Temp{
        String flag = "";

        public Temp(String flag) {
            this.flag = flag;
        }

        public String getFlag() {
            return flag;
        }

        public void setFlag(String flag) {
            this.flag = flag;
        }
    }
}
